package br.com.future.interceptors;

import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import br.com.future.constants.Headers;
import br.com.future.securityContext.SecurityContext;
import br.com.future.securityContext.SecurityContextUtils;

/**
 * This is the first controller that will create SecurityContext and feed it with request information.
 *
 * @author Rafael Castanho Ferreira (mailto: rafa.ferreira@gmail.com)
 * @since 02-2011
 */
public class IntializerInterceptor extends HandlerInterceptorAdapter {

	private static final Log LOG = LogFactory.getLog(IntializerInterceptor.class);

	/*
	 * @see org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet .http.HttpServletRequest,
	 * javax.servlet.http.HttpServletResponse, java.lang.Object)
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

		if(LOG.isDebugEnabled())
			LOG.debug("IntializerInterceptor - request received");

		SecurityContext sc = SecurityContextUtils.getSecurityContextFromRequest(request);

		/*
		 * SecurityContext shall be null on this point. This IntializerInterceptor shall be the first so, if something
		 * is not null here some one send the header on request, and this is INVALID!
		 *
		 * Hacking tentative????? Wooooooot!
		 */
		if(null != sc) {
			LOG.warn(Headers.HEADER_SECUTIRY_CONTEXT + " found on request! This is NOT normal!");
			request.removeAttribute(Headers.HEADER_SECUTIRY_CONTEXT);
		}

		/*
		 * Instantiate a new SecurityContext and add to request
		 * Remembering that on SecurityContext we create a trackId that is a UUID
		 */
		if(LOG.isDebugEnabled())
			LOG.debug("Creating and adding SecurityContext to request");
		SecurityContextUtils.setSecurityContextToRequest(request, new SecurityContext());

		/*
		 * Extract all headers from request and add to Map
		 */
		extractHeadersFromRequest(request);

		return true;
	}

	/*
	 * @see org.springframework.web.servlet.HandlerInterceptor#postHandle(javax.servlet .http.HttpServletRequest,
	 * javax.servlet.http.HttpServletResponse, java.lang.Object)
	 */
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		if (LOG.isDebugEnabled())
			LOG.debug("IntializerInterceptor - postHandle");
	}

	/*
	 * @see org.springframework.web.servlet.HandlerInterceptor#afterCompletion(javax .servlet.http.HttpServletRequest,
	 * javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
	 */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception exception) throws Exception {

		LOG.info("IntializerInterceptor - Writing out response content");
		SecurityContext sc = SecurityContextUtils.getSecurityContextFromRequest(request);

		/*
		 * This is a important part, any interceptor that could found some error/validation, will return false!
		 * And the subsequential interceptors will not be called, I'm the last interceptor, and I shall get the error
		 * from SecurityContext and print out on HttpServletResponse.
		 */
		if (null != sc.getResponseContent()) {
			PrintWriter out = response.getWriter();
			out.write(sc.getResponseContent());
			response.setStatus(sc.getResponseStatusCode());
		}
	}

	@SuppressWarnings("unchecked")
	private void extractHeadersFromRequest(HttpServletRequest request) {
		SecurityContext sc = SecurityContextUtils.getSecurityContextFromRequest(request);
		Enumeration<String> en = request.getHeaderNames();
		while (en.hasMoreElements()) {
			String headerName = en.nextElement();
			sc.addHeader(headerName, request.getHeader(headerName));
		}
	}
}
